package com.gis.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gis.entity.ScriptData;
import com.gis.enums.ApiErrorCode;
import com.gis.exception.ApiException;
import com.gis.mapper.ScriptMapper;
import com.gis.service.ScriptService;
import com.gis.utils.ZipExtraUtil;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class ScriptServiceImpl extends ServiceImpl<ScriptMapper, ScriptData> implements ScriptService {

    @Value("${files.dir}/${files.relative-save-dir}/${files.script}")
    private String scriptDir;

    @Override
    public String runScript(List<String> script) throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public HashMap<String, Object> addScript(MultipartFile file, String description, Integer inputNum, Integer outputNum, String outputType, String inputType) throws Exception {
        // TODO Auto-generated method stub
        HashMap<String, Object> result = new HashMap<>();
        try {
            // 保存文件
            String originalFilename = file.getOriginalFilename();
            String uuid = UUID.randomUUID().toString();
            String savedFileName = uuid + "_" + originalFilename;
            String filePath = scriptDir + originalFilename;
            String savedDirName = uuid + "_" + originalFilename.substring(0, originalFilename.lastIndexOf("."));
            File destDir = new File(scriptDir + "/" + savedDirName);

            // 判断脚本文件是否已存在
            QueryWrapper<ScriptData> qw = new QueryWrapper<>();
            qw.eq("origin_name", originalFilename)
                    .eq("saved_dir", destDir.getAbsolutePath());
            ScriptData duplicate = this.getOne(qw);
            if (duplicate != null) {
//                result.put("code", 400);
//                result.put("msg", "同名脚本已存在");
//                return result;
                throw new ApiException(ApiErrorCode.FILE_EXISTS);
            }

            // 判断文件路径是否为存在
            if (!destDir.exists()) {
                destDir.mkdirs();
            }

            File uploadFile = new File(destDir + "/" + savedFileName);
            file.transferTo(uploadFile);

            result.put("originalFilename", originalFilename);
            result.put("savedFileName", savedFileName);
            result.put("uuid", uuid);

            ScriptData scriptData = new ScriptData();
            scriptData.setOriginName(originalFilename);
            scriptData.setSavedName(savedFileName);
            scriptData.setSavedDir(scriptDir + "/" + savedDirName);
            scriptData.setFileDescription(description);
            scriptData.setFileType("script");
            scriptData.setInputNum(inputNum);
            scriptData.setOutputNum(outputNum);
            scriptData.setOutputType(outputType);
            this.save(scriptData);

            result.put("msg", "添加脚本成功");
            result.put("code", 200);
            result.put("savedDir", scriptDir + "/" + savedDirName);
            result.put("fileName", savedFileName);
            result.put("data", scriptData);
        } catch (Exception e) {
            e.printStackTrace();
            result.put("msg", "添加脚本失败");
            result.put("code", 500);
            result.put("data", e.getMessage());
        }
        return result;
    }

    @Override
    public HashMap<String, Object> deleteScript(Integer scriptId) throws Exception {
        HashMap<String, Object> result = new HashMap<>();
        ScriptData scriptData = getById(scriptId);
        try {
            Path path = Paths.get(scriptData.getSavedDir().trim());
            if (!Files.exists(path)) {
                result.put("msg", "路径不存在");
                result.put("result", false);
            }
            if (!Files.isDirectory(path)) {
                result.put("msg", "任务路径不是目录");
                result.put("result", false);
            }
            if (!Files.isWritable(path)) {
                result.put("msg", "没有权限删除目录");
                result.put("result", false);
            }
            Files.walk(path)
                    //先删子文件 逆序排序
                    .sorted(Comparator.reverseOrder())
                    //反射 path-file map
                    .map(Path::toFile)
                    //反射 删除方法
                    .forEach(File::delete);
            if(removeById(scriptId)){
                result.put("msg", "成功删除目录");
                result.put("result", true);
            }else{
                result.put("msg", "数据表删除失败");
                result.put("result", true);
            }
        } catch (IOException e) {
            result.put("msg", "删除目录出错");
            result.put("result", false);
        }
        return result;
    }

    @Override
    public HashMap<String, Object> addScriptZip(MultipartFile file, String description, Integer inputNum, Integer outputNum, String outputType, String inputType) throws Exception {
        HashMap<String, Object> result = this.addScript(file, description, inputNum, outputNum, outputType, inputType);
        if (result.get("fileName") != null) {
            String fileName = (String) result.get("fileName");
            String savedDir = (String) result.get("savedDir");
            String filePath = savedDir + "/" + fileName;
            // 解压文件
            ZipExtraUtil.unzip(filePath, savedDir);
            ScriptData scriptData = (ScriptData) result.get("data");
            scriptData.setSavedDir(savedDir);
            scriptData.setOriginName(file.getOriginalFilename().replace(".zip", ".exe"));
            this.updateById(scriptData);
        }
        return result;
    }


    
}
